package com.crowd.web.config;

import com.crowd.constant.CrowdConstant;
import com.crowd.exception.AccessForbbidenException;
import com.crowd.exception.LoginAccountAlreadyExistException;
import com.crowd.exception.LoginFailedException;
import com.crowd.util.CrowdUtil;
import com.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Stone
 * @date 2020/4/29 21:11
 */
@ControllerAdvice
public class CrowdExceptionResolver {

    Logger logger = LoggerFactory.getLogger(CrowdExceptionResolver.class);

    /**
     * @Author:Stone
       * @Param request:
     * @Param response:
     * @Param e: 异常类型
     * @Param viewName: 视图名
       * @return: org.springframework.web.servlet.ModelAndView
     * @Date: 2020/5/7
     * @Description:抽取公共代码，写成一个公共类
    */
    public ModelAndView commonResolver(HttpServletRequest request, HttpServletResponse response,Exception e,String viewName) throws IOException {
        //1.判断是页面请求还是ajax请求
        boolean judgeResult = CrowdUtil.judgeRequestType(request);
        //2.如果是ajax请求
        if(judgeResult){
            //2.1从异常对象里面获取异常信息
            String message = e.getMessage();
            //2.2使用ResultEntity.failed(String msg)方法，返回错误信息
            ResultEntity<Object> resultEntity = ResultEntity.failed(message);
            //2.3用Gson把异常信息2使用ResultEntity对象转为json返回
            Gson gson = new Gson();
            String json = gson.toJson(resultEntity);
            logger.info(json);
            response.getWriter().write(json);
            return null;
        }
        //3.如果是页面请求
        ModelAndView modelAndView = new ModelAndView();
        //3.1返回异常对象
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION,e);
        //3.2返回异常页面
        modelAndView.setViewName(viewName);
        return modelAndView;
    }

    /**
     * @Author:Stone
       * @Param request:
     * @Param response:
     * @Param e:
       * @return: org.springframework.web.servlet.ModelAndView
     * @Date: 2020/5/8 16:18
     * @Description:用于解决空指针异常
    */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(HttpServletRequest request, HttpServletResponse response,NullPointerException e) throws IOException {
        String viewName = "/error";
        return commonResolver(request,response,e,viewName);
    }

    /**
     * @Author:Stone
       * @Param request:
     * @Param response:
     * @Param e:
       * @return: org.springframework.web.servlet.ModelAndView
     * @Date: 2020/5/8 16:18
     * @Description:用于解决算术异常
    */
    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveArithmeticException(HttpServletRequest request, HttpServletResponse response,ArithmeticException e) throws IOException {
        String viewName = "/error";
        return commonResolver(request,response,e,viewName);
    }

    /**
     * @Author:Stone
     * @Param request:
     * @Param response:
     * @Param e:
     * @return: org.springframework.web.servlet.ModelAndView
     * @Date: 2020/5/8 16:18
     * @Description:用于解决算术异常
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(HttpServletRequest request, HttpServletResponse response,LoginFailedException e) throws IOException {
        String viewName = "/admin-login";
        return commonResolver(request,response,e,viewName);
    }

    /**
     * @Author:Stone
       * @Param request:
     * @Param response:
     * @Param e:
       * @return: org.springframework.web.servlet.ModelAndView
     * @Date: 2020/5/9 15:44
     * @Description:用于解决用户未登录就访问主页的异常
    */
    @ExceptionHandler(value = AccessForbbidenException.class)
    public ModelAndView resolveAccessForbbidenException(HttpServletRequest request, HttpServletResponse response,AccessForbbidenException e) throws IOException {
        String viewName = "/admin-login";
        return commonResolver(request,response,e,viewName);
    }

    @ExceptionHandler(value = LoginAccountAlreadyExistException.class)
    public ModelAndView resolveLoginAccountAlreadyExistException(HttpServletRequest request, HttpServletResponse response,LoginAccountAlreadyExistException e) throws IOException {
        String viewName = "/admin-add";
        return commonResolver(request,response,e,viewName);
    }

    @ExceptionHandler(value = AccessDeniedException.class)
    public ModelAndView resolveAccessDeniedException(HttpServletRequest request, HttpServletResponse response,AccessDeniedException e) throws IOException {
        String viewName = "/error";
        return commonResolver(request,response,e,viewName);
    }
}
